package com.chinairi.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinairi.common.utils.RedisUtil;
import com.chinairi.common.utils.UserSession;
import com.chinairi.mall.controller.viewobject.OrderServiceTransportVO;
import com.chinairi.mall.controller.viewobject.ProjectPlanPickingOrderVO;
import com.chinairi.mall.controller.viewobject.ProjectPlanPickingVO;
import com.chinairi.mall.controller.viewobject.ProjectPlanReqVO;
import com.chinairi.mall.dao.*;
import com.chinairi.mall.model.*;
import com.chinairi.mall.service.IProjectPlanPickingService;
import com.chinairi.mall.service.modelobject.MatServiceInfoMO;
import com.chinairi.mall.service.modelobject.ProjectPlanPickingDetailMO;
import com.chinairi.mall.service.modelobject.StorageFlatMO;
import com.chinairi.mall.service.modelobject.UserInfoToRedisMO;
import com.chinairi.mall.util.VerificationCodeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 领料单 服务实现类
 * </p>
 *
 * @author Webgasd
 * @since 2020-10-13
 */
@Service
public class ProjectPlanPickingServiceImpl extends ServiceImpl<ProjectPlanPickingMapper, ProjectPlanPicking> implements IProjectPlanPickingService {
    @Autowired
    private ProjectPlanPickingMapper projectPlanPickingMapper;
    @Autowired
    protected ProjectPlanPickingDetailMapper projectPlanPickingDetailMapper;
    @Autowired
    private ProjectPlanReqDetailMapper projectPlanReqDetailMapper;
    @Autowired
    private ProjectPlanReqStorageMapper projectPlanReqStorageMapper;
    @Autowired
    private OrderServiceTransportMapper orderServiceTransportMapper;
    @Autowired
    private OrderServiceTransportGoodsMapper orderServiceTransportGoodsMapper;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private UserCompanyInfoServiceImpl userCompanyInfoService;
    @Autowired
    private SysUserServiceImpl sysUserService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private StorageAddressMapper storageAddressMapper;

    /**
     * 企业编码和名称互换。
     *
     * @param uciDbId
     * @return
     */
    public String getUnitName(String uciDbId) {
        Map<Object, Object> compMapResult = redisUtil.hmget("compMap");
        if (compMapResult.isEmpty() || compMapResult.get(uciDbId) == null) {
            userCompanyInfoService.putRedis();
        }
        return (String) redisUtil.hmget("compMap").get(uciDbId);
    }

    /**
     * 添加新的领料单,此时是暂存状态，状态值应当赋值为第一步，然后用户再次进入领料单界面，可以看到服务单状态，单独选择服务即可。
     * 包括退单这种情况，也是一个单选服务的状态。
     *
     * @param projectPlanPickingVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(ProjectPlanPickingVO projectPlanPickingVo) {
        ProjectPlanPicking projectPlanPicking = new ProjectPlanPicking();
        BeanUtils.copyProperties(projectPlanPickingVo, projectPlanPicking);
        String pppId = VerificationCodeUtil.DateCreate(new Date());
        projectPlanPicking.setPppId(pppId);
        projectPlanPicking.setPppStatus("0");
        StorageAddress storageAddress = storageAddressMapper.selectById(projectPlanPicking.getPppStorageDbid());
        projectPlanPicking.setPppStorageAddress(storageAddress.getSaAddress());
        projectPlanPicking.setPppStorePerson(storageAddress.getSaMan());
        projectPlanPicking.setPppStorePersonPhone(storageAddress.getSaManPhone());
        projectPlanPicking.setPppApplyDate(new Date());
        projectPlanPickingMapper.insert(projectPlanPicking);
        /**
         * 批量插入子表前做数据处理。
         * 插入领料子表
         */
        List<ProjectPlanPickingDetailMO> projectPlanPickingDetailMOList = projectPlanPickingVo.getProjectPlanPickingDetailMOList();
        if (projectPlanPickingDetailMOList.size() > 0) {
            projectPlanPickingDetailMapper.batchInsertDetail(projectPlanPickingDetailMOList.stream().peek((list) -> {
                list.setPppdDbid(UUID.randomUUID().toString().replace("-", ""));
                list.setPppId(pppId);
                list.setPppdStatus("0");
                list.setCreateUser(UserSession.getUserId());
                list.setPppdSeq(0);
                list.setCreateTime(new Date());
            }).collect(Collectors.toList()));
            /*
            查找库存表，需求清单表
             */
            List<StorageFlatMO> storageFlatMoList = projectPlanPickingDetailMapper.selectPickAndStorage(pppId);
            if (storageFlatMoList.size() > 0) {
                for (StorageFlatMO storageFlatMo : storageFlatMoList) {
                    float havePicked = storageFlatMo.getPppdPickNumber();
                    storageFlatMo.setPlanReqNumNow(storageFlatMo.getPlanReqNumNow() - havePicked);
                    storageFlatMo.setPlanFlatNum(storageFlatMo.getPlanFlatNum() - havePicked);
                    storageFlatMo.setPlanCollectedNum(storageFlatMo.getPlanCollectedNum() + havePicked);
                    storageFlatMo.setFlatNum(storageFlatMo.getFlatNum() - havePicked);
                    storageFlatMo.setHavePickNum(storageFlatMo.getHavePickNum() + havePicked);
                }
                projectPlanReqDetailMapper.batchUpdateByPick(storageFlatMoList);
                projectPlanReqStorageMapper.batchUpdateByPick(storageFlatMoList);
            }
        }
    }

    /**
     * 筛选回传的物料list
     *
     * @param projectPlanReqVo
     * @return ProjectPlanPickingVO
     */
    @Override
    public ProjectPlanPickingVO getCanPickList(ProjectPlanReqVO projectPlanReqVo) {
        List<String> planMatCodeList = getMatDbIdList(projectPlanReqVo.getProjectPlanReqDetailList());
        if (planMatCodeList.size() > 0) {
            ProjectPlanPickingVO projectPlanPickingVO = new ProjectPlanPickingVO();
            //planMatCodeList 物料list
            List<ProjectPlanPickingDetailMO> projectPlanPickingDetailMoList = projectPlanPickingDetailMapper.selectListByList(planMatCodeList, projectPlanReqVo.getPlanReqId(), projectPlanReqVo.getSaDbId());
            if (projectPlanPickingDetailMoList.size() > 0) {
                projectPlanPickingVO.setProjectPlanPickingDetailMOList(projectPlanPickingDetailMoList);
                projectPlanPickingVO.setPppProjectId(projectPlanReqVo.getpId());
                projectPlanPickingVO.setPppProjectName(projectPlanReqVo.getpName());
                projectPlanPickingVO.setPlanReqId(projectPlanReqVo.getPlanReqId());
                projectPlanPickingVO.setPppUnitDbid(projectPlanReqVo.getUciDbid());
                projectPlanPickingVO.setPppUnitName(getUnitName(projectPlanReqVo.getUciDbid()));
                projectPlanPickingVO.setPppStorageDbid(projectPlanReqVo.getSaDbId());
                projectPlanPickingVO.setPppProjectId(projectPlanPickingDetailMoList.get(0).getPppStorageName());
                return projectPlanPickingVO;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 根据list筛选物料编码列表
     *
     * @param projectPlanReqDetailList
     * @return
     */
    public List<String> getMatDbIdList(List<ProjectPlanReqDetail> projectPlanReqDetailList) {
        List<String> matCodeList = new ArrayList<>();
        if (projectPlanReqDetailList.size() > 0) {
            for (ProjectPlanReqDetail projectPlanReqDetail : projectPlanReqDetailList) {
                if (projectPlanReqDetail.getPlanFlatNum() > 0) {
                    matCodeList.add(projectPlanReqDetail.getPlanMatCode());
                }
            }
        }
        return matCodeList;
    }

    /**
     * 获取list
     *
     * @return
     */
    @Override
    public List<ProjectPlanPicking> getList() {
        UserInfoToRedisMO userInfoToRedisMo = sysUserService.getUserInfoFromRedis(UserSession.getUserId());
        QueryWrapper<ProjectPlanPicking> wrapper = new QueryWrapper<>();
        wrapper
                .eq(StringUtils.isNotEmpty(userInfoToRedisMo.getUciDbid()), "PPP_UNIT_DBID", userInfoToRedisMo.getUciDbid())
        .orderByDesc("PPP_APPLY_DATE");
        return projectPlanPickingMapper.selectList(wrapper);
    }

    /**
     * 根据某个领料单id获取领料单详细订单
     *
     * @param pickId
     * @return
     */
    @Override
    public ProjectPlanPickingOrderVO getOneByPickId(String pickId) {
        ProjectPlanPickingOrderVO projectPlanPickingOrderVO = new ProjectPlanPickingOrderVO();
        QueryWrapper<ProjectPlanPicking> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(pickId), "PPP_ID", pickId);
        ProjectPlanPicking projectPlanPicking = projectPlanPickingMapper.selectOne(wrapper);
        projectPlanPickingOrderVO.setProjectPlanPicking(projectPlanPicking);
        List<ProjectPlanPickingDetail> projectPlanPickingDetailList = projectPlanPickingDetailMapper.getListByPickId(pickId);
        projectPlanPickingOrderVO.setProjectPlanPickingDetailList(projectPlanPickingDetailList);
        return projectPlanPickingOrderVO;
    }

    /**
     * 查看当前领料单下的所有物流服务
     *
     * @param pickId
     * @return
     */
    @Override
    public List<OrderServiceTransport> getOrderServiceTransportList(String pickId) {
        QueryWrapper<OrderServiceTransport> wrapper = new QueryWrapper<>();
        wrapper
                .eq(StringUtils.isNotEmpty(pickId), "ORDER_ID", pickId);
        return orderServiceTransportMapper.selectList(wrapper);
    }

    /**
     * 查看当前物流服务下的所有物料及其信息。
     *
     * @param ostId
     * @return
     */
    @Override
    public OrderServiceTransportVO getOrderServiceInfo(String ostId) {
        OrderServiceTransportVO orderServiceTransportVo = new OrderServiceTransportVO();
        OrderServiceTransport orderServiceTransport = orderServiceTransportMapper.selectById(ostId);
        BeanUtils.copyProperties(orderServiceTransport, orderServiceTransportVo);
        QueryWrapper<OrderServiceTransportGoods> wrapper = new QueryWrapper<>();
        wrapper
                .eq(StringUtils.isNotEmpty(ostId), "OST_ID", ostId);
        List<OrderServiceTransportGoods> orderServiceTransportGoodsList = orderServiceTransportGoodsMapper.selectList(wrapper);
        orderServiceTransportVo.setOrderServiceTransportGoodsList(orderServiceTransportGoodsList);
        return orderServiceTransportVo;
    }

    /**
     * 替换回传服务小类和flag
     *
     * @param type
     * @return
     */
    private Integer getFlag(String type) {
        //服务分类的标志位
        Map<String, Integer> flagMap = new HashMap<>(12);
        flagMap.put("fwfl005", 0);
        flagMap.put("fwfl006", 1);
        flagMap.put("fwfl007", 0);
        flagMap.put("fwfl008", 0);
        flagMap.put("fwfl009", 0);
        flagMap.put("fwfl010", 0);
        flagMap.put("fwfl011", 1);
        flagMap.put("fwfl012", 1);
        flagMap.put("fwfl013", 1);
        flagMap.put("fwfl016", 0);
        flagMap.put("fwfl017", 0);
        flagMap.put("fwfl018", 0);

        return flagMap.get(type);
    }

    /**
     * 获取所选物料列表的详情列表主键
     *
     * @param projectPlanPickingDetailList
     * @return
     */
    private List<String> getDetailIdList(List<ProjectPlanPickingDetail> projectPlanPickingDetailList) {
        List<String> detailIdList = new ArrayList<>();
        for (ProjectPlanPickingDetail projectPlanPickingDetail : projectPlanPickingDetailList) {
            detailIdList.add(projectPlanPickingDetail.getPppdDbid());
        }
        return detailIdList;
    }

    /**
     * 获取物流服务的所有信息
     *
     * @param projectPlanPickingOrderVo
     * @param detailIdList
     * @return
     */
    private OrderServiceTransportVO getOrderServiceTransportVO(ProjectPlanPickingOrderVO projectPlanPickingOrderVo, List<String> detailIdList) {
        OrderServiceTransportVO orderServiceTransportVo = projectPlanPickingOrderVo.getOrderServiceTransportVO();

        String pppId = projectPlanPickingOrderVo.getProjectPlanPicking().getPppId();
        orderServiceTransportVo.setOrderId(pppId);

        orderServiceTransportVo.setOstState("0");
        orderServiceTransportVo.setOstFlag("1");
        //获取物料在物流服务中的详细类型列表
        String serviceClass = orderServiceTransportVo.getOstTransportType();
        List<MatServiceInfoMO> matServiceInfoMoList = projectPlanPickingDetailMapper.selectMatServiceInfo(detailIdList, serviceClass, getFlag(serviceClass), orderServiceTransportVo.getOstShopId());
        if (matServiceInfoMoList.size() > 0) {
            List<OrderServiceTransportGoods> orderServiceTransportGoodsList = new ArrayList<>();
            if (getFlag(serviceClass) == 0) {
                List<ProjectPlanPickingDetail> projectPlanPickingDetailList = projectPlanPickingOrderVo.getProjectPlanPickingDetailList();
                for (ProjectPlanPickingDetail projectPlanPickingDetail : projectPlanPickingDetailList) {
                    OrderServiceTransportGoods orderServiceTransportGoods = new OrderServiceTransportGoods();

                    orderServiceTransportGoods.setOstgGoodsDbid(projectPlanPickingDetail.getPppdMatDbid());
                    orderServiceTransportGoods.setOstgGoodsName(projectPlanPickingDetail.getPppdMatName());
                    orderServiceTransportGoods.setOstgOrderId(projectPlanPickingDetail.getPppdDbid());
                    orderServiceTransportGoods.setOstgUciName(matServiceInfoMoList.get(0).getCsDbid());
                    orderServiceTransportGoods.setOstgGoodsNumber(projectPlanPickingDetail.getPppdPickNumber());
                    orderServiceTransportGoods.setOstgGoodsUnit(projectPlanPickingDetail.getPppdMeasurement());
                    orderServiceTransportGoods.setOstgDeliveryAddress(projectPlanPickingDetail.getPppStorageAddress());
                    orderServiceTransportGoods.setOstgReceiveAddress(projectPlanPickingDetail.getPppdArrivalAddress());
                    orderServiceTransportGoods.setOstgTransportDistance((float) 100);
                    orderServiceTransportGoods.setOstgValuationUnit(matServiceInfoMoList.get(0).getSpPriceUnit());
                    orderServiceTransportGoods.setOstgTransportPrice(matServiceInfoMoList.get(0).getSpServiceCharge());
                    orderServiceTransportGoods.setOstgEstimateDay("10");
                    orderServiceTransportGoods.setOstgRailwayMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgRoadEstimateMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgRoadMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgWaterWayMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgTransferMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgEstimateMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgMoney(new BigDecimal(0));
                    orderServiceTransportGoodsList.add(orderServiceTransportGoods);
                }
            } else if (getFlag(serviceClass) == 1) {
                for (MatServiceInfoMO matServiceInfoMo : matServiceInfoMoList) {
                    OrderServiceTransportGoods orderServiceTransportGoods = new OrderServiceTransportGoods();

                    orderServiceTransportGoods.setOstgGoodsDbid(matServiceInfoMo.getPppdMatDbid());
                    orderServiceTransportGoods.setOstgGoodsName(matServiceInfoMo.getPppdMatName());
                    orderServiceTransportGoods.setOstgOrderId(matServiceInfoMo.getPppdDbid());
                    orderServiceTransportGoods.setOstgUciName(matServiceInfoMo.getCsDbid());
                    orderServiceTransportGoods.setOstgGoodsNumber(matServiceInfoMo.getPppdPickNumber());
                    orderServiceTransportGoods.setOstgGoodsUnit(matServiceInfoMo.getPppdMeasurement());
                    orderServiceTransportGoods.setOstgDeliveryAddress(matServiceInfoMo.getPppStorageAddress());
                    orderServiceTransportGoods.setOstgReceiveAddress(matServiceInfoMo.getPppdArrivalAddress());
                    orderServiceTransportGoods.setOstgTransportDistance((float) 100);
                    orderServiceTransportGoods.setOstgValuationUnit(matServiceInfoMo.getSpPriceUnit());
                    orderServiceTransportGoods.setOstgTransportPrice(matServiceInfoMo.getSpServiceCharge());
                    orderServiceTransportGoods.setOstgEstimateDay("10");
                    orderServiceTransportGoods.setOstgRailwayMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgRoadEstimateMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgRoadMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgWaterWayMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgTransferMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgEstimateMoney(new BigDecimal(0));
                    orderServiceTransportGoods.setOstgMoney(new BigDecimal(0));
                    orderServiceTransportGoodsList.add(orderServiceTransportGoods);
                }
            }
            orderServiceTransportVo.setOrderServiceTransportGoodsList(orderServiceTransportGoodsList);
        }
        return orderServiceTransportVo;
    }

    /**
     * 获取服务详情
     *
     * @param projectPlanPickingOrderVo
     * @return
     */
    @Override
    public ProjectPlanPickingOrderVO getServiceInfo(ProjectPlanPickingOrderVO projectPlanPickingOrderVo) {
        List<ProjectPlanPickingDetail> projectPlanPickingDetailList = projectPlanPickingOrderVo.getProjectPlanPickingDetailList();
        List<String> detailIdList = getDetailIdList(projectPlanPickingDetailList);
        OrderServiceTransportVO orderServiceTransportVo = getOrderServiceTransportVO(projectPlanPickingOrderVo, detailIdList);
        projectPlanPickingOrderVo.setOrderServiceTransportVO(orderServiceTransportVo);
        return projectPlanPickingOrderVo;
    }

    /**
     * 添加一个领料的物流订单
     *
     * @param projectPlanPickingOrderVo
     */
    @Override
    public void addPickOrder(ProjectPlanPickingOrderVO projectPlanPickingOrderVo) {
        ProjectPlanPicking projectPlanPicking = projectPlanPickingOrderVo.getProjectPlanPicking();
        projectPlanPicking.setPppStatus("2");
        projectPlanPickingMapper.updateById(projectPlanPicking);
        batchUpdateState(projectPlanPickingOrderVo.getProjectPlanPickingDetailList(),"1");
        if (projectPlanPickingOrderVo.getOrderServiceTransportVO() != null) {
            OrderServiceTransport orderServiceTransport = new OrderServiceTransport();
            String ostId = VerificationCodeUtil.DateCreate(new Date());
            BeanUtils.copyProperties(projectPlanPickingOrderVo.getOrderServiceTransportVO(), orderServiceTransport);
            orderServiceTransport.setOstId(ostId);
            orderServiceTransport.setOstState("0");
            orderServiceTransport.setCreateUserId(UserSession.getUserId());
            orderServiceTransport.setCreateUser(UserSession.getUserName());
            orderServiceTransportMapper.insert(orderServiceTransport);
            List<OrderServiceTransportGoods> orderServiceTransportGoodsList = projectPlanPickingOrderVo.getOrderServiceTransportVO().getOrderServiceTransportGoodsList();
            orderInfoMapper.batchInsertServiceTransportGoods(orderServiceTransportGoodsList.stream().peek((list) -> {
                list.setOstgId(UUID.randomUUID().toString().replace("-", ""));
                list.setOstId(ostId);
                list.setCreateUser(UserSession.getUserId());
                list.setCreateTime(new Date());
            }).collect(Collectors.toList()));
        }
    }

    /**
     * 撤销不通过的订单
     * @param beforeOrderId
     */
    @Override
    public void deleteServiceOrder(String beforeOrderId){
        List<String> detailIdList = getDetailIdList(beforeOrderId);
        if (detailIdList.size() > 0) {
            List<ProjectPlanPickingDetail> projectPlanPickingDetailList = getDetailList(detailIdList);
            batchUpdateState(projectPlanPickingDetailList,"0");
            updateServiceOrder(beforeOrderId,"9");
        }
    }

    /**
     * 批量更新领料详单的物料状态
     * @param projectPlanPickingDetailList
     * @param type
     */
    private void batchUpdateState(List<ProjectPlanPickingDetail> projectPlanPickingDetailList, String type) {
        projectPlanPickingDetailMapper.batchUpdateState(projectPlanPickingDetailList.stream().peek((list) -> {
            list.setPppdStatus(type);
            list.setUpdateUser(UserSession.getUserId());
            list.setUpdateTime(new Date());
        }).collect(Collectors.toList()));
    }

    /**
     * 获取领料单物料表主键列
     * @param beforeOrderId
     * @return
     */
    private List<String> getDetailIdList(String beforeOrderId){
        return projectPlanPickingDetailMapper.selectDetailIdList(beforeOrderId);
    }

    /**
     * 根据主键列获取所有数据
     * @param detailIdList
     * @return
     */
    private List<ProjectPlanPickingDetail> getDetailList(List<String> detailIdList){
        return projectPlanPickingDetailMapper.getListByDetailList(detailIdList);
    }

    /**
     * 更新订单状态为某个值
     * @param beforeOrderId
     */
    private void updateServiceOrder(String beforeOrderId, String item){
        //将原订单状态置为9，表示不可用
        OrderServiceTransport lastOrder = new OrderServiceTransport();
        lastOrder.setOstId(beforeOrderId);
        lastOrder.setOstState(item);
        orderServiceTransportMapper.updateById(lastOrder);
    }

    /**
     * 务必回传原订单的订单号，以及换新的所有服务信息，同原来的方法，无需回传物料列表，后端自己获取即可。
     *
     * @param projectPlanPickingOrderVo
     */
    @Override
    public ProjectPlanPickingOrderVO updateServiceOfPickOrder(ProjectPlanPickingOrderVO projectPlanPickingOrderVo) {
        String beforeOstId = projectPlanPickingOrderVo.getBeforeOrderId();
        OrderServiceTransport orderServiceTransport = orderServiceTransportMapper.selectById(beforeOstId);
        ProjectPlanPicking projectPlanPicking = new ProjectPlanPicking();
        projectPlanPicking.setPppId(orderServiceTransport.getOrderId());
        projectPlanPickingOrderVo.setProjectPlanPicking(projectPlanPicking);
        List<String> detailIdList = getDetailIdList(beforeOstId);
        if (detailIdList.size() > 0) {
            List<ProjectPlanPickingDetail> projectPlanPickingDetailList = getDetailList(detailIdList);
            if (projectPlanPickingDetailList.size() > 0) {
                projectPlanPickingOrderVo.setProjectPlanPickingDetailList(projectPlanPickingDetailList);
            }
        }
        OrderServiceTransportVO orderServiceTransportVo = getOrderServiceTransportVO(projectPlanPickingOrderVo, detailIdList);
        projectPlanPickingOrderVo.setOrderServiceTransportVO(orderServiceTransportVo);
        //将原订单状态置为9，表示不可用
        updateServiceOrder(beforeOstId,"9");
        return projectPlanPickingOrderVo;
    }
}
